﻿using System;
using System.Collections;
using System.Collections.Specialized;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace LogParser
{
    public partial class LogParser : Form
    {
        private delegate void UpdateResposeResultEventHandler(IBdiHttpWebResponse bdiResponse);
        AutoSizeFormClass asc = new AutoSizeFormClass();
        private ArrayList list = null;
        private const int PageCount = 100;
        private int currentPage = 1;
        private Int64 selectIndex;
        private ArrayList responseList = new ArrayList();

        public LogParser()
        {
            InitializeComponent();

            Initialize();
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                txtLogFile.Text = dialog.FileName;
            }

        }

        private void btnLoad_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txtLogFile.Text))
            {
                MessageBox.Show("Please select Log File!");
                return;
            }

            list = BdiFileParser.ReadFile(txtLogFile.Text);

            btnPrev.Enabled = false;
            int count = list.Count;
            if (list.Count > PageCount)
            {
                count = PageCount;
                btnNext.Enabled = true;
            }
            else
            {
                btnNext.Enabled = false;
            }

            lstLogitem.BeginUpdate();
            lstLogitem.Items.Clear();
            for (int i = 0; i < count; i++)
            {
                lstLogitem.Items.Add(list[i]);
            }
            lstLogitem.EndUpdate();
            currentPage = 1;
            lblCurrent.Text = currentPage.ToString();
            int pageNumber = list.Count / PageCount;
            if (list.Count % PageCount > 0)
            {
                pageNumber += 1;
            }
            lblTotal.Text = pageNumber.ToString();
        }

        private void btnPrev_Click(object sender, EventArgs e)
        {
            currentPage--;

            lstLogitem.BeginUpdate();
            lstLogitem.Items.Clear();
            for (int i = (currentPage - 1) * PageCount; i < currentPage * PageCount; i++)
            {
                lstLogitem.Items.Add(list[i]);
            }
            lstLogitem.EndUpdate();
            if (currentPage == 1)
            {
                btnPrev.Enabled = false;
            }
            else
            {
                btnPrev.Enabled = true;
            }
            btnNext.Enabled = true;
            lblCurrent.Text = currentPage.ToString();
        }

        private void btnNext_Click(object sender, EventArgs e)
        {
            int count = list.Count;
            if (list.Count - currentPage * PageCount > PageCount)
            {
                count = (currentPage + 1) * PageCount;
                btnNext.Enabled = true;
            }
            else
            {
                btnNext.Enabled = false;
            }

            lstLogitem.BeginUpdate();
            lstLogitem.Items.Clear();
            for (int i = currentPage * PageCount; i < count; i++)
            {
                lstLogitem.Items.Add(list[i]);
            }
            lstLogitem.EndUpdate();

            currentPage++;
            btnPrev.Enabled = true;
            lblCurrent.Text = currentPage.ToString();
        }

        private void lstLogitem_MouseMove(object sender, MouseEventArgs e)
        {
            int index = lstLogitem.IndexFromPoint(e.Location);
            // Check if the index is valid.
            if (index != -1 && index < lstLogitem.Items.Count)
            {
                // Check if the ToolTip's text isn't already the one
                // we are now processing.
                if (toolTip1.GetToolTip(lstLogitem) != (lstLogitem.Items[index].ToString().Substring(0, 200) + "..."))
                {
                    // If it isn't, then a new item needs to be
                    // displayed on the toolTip. Update it.
                    toolTip1.SetToolTip(lstLogitem, lstLogitem.Items[index].ToString().Substring(0, 200) + "...");
                }
            }
        }

        private void lstLogitem_MouseClick(object sender, MouseEventArgs e)
        {
            string strHeader = BdiFileParser.GetRequestHeader(lstLogitem.SelectedItem.ToString());

            string[] headers = strHeader.Split('|');
            strHeader = string.Empty;
            foreach (string header in headers)
            {
                if (string.IsNullOrEmpty(header))
                {
                    continue;
                }
                if (!string.IsNullOrEmpty(strHeader))
                {
                    strHeader += Environment.NewLine;
                }
                int index = header.IndexOf("=");
                if (index > 0)
                {
                    if (header.Substring(0, index).ToUpper() == "X-FD-APPID")
                    {
                        strHeader += header.Substring(0, index) + ":" + "CDDD89A468E3781699EA1FA5D91447230DCD5E6A";
                    }
                    else
                    {
                        strHeader += header.Substring(0, index) + ":" + header.Substring(index + 1);
                    }
                }
            }

            txtHeader.Text = strHeader;

            string strBody;
            AdBaseRequestParser.GetBingRequestBody(BdiFileParser.GetRequestBody(lstLogitem.SelectedItem.ToString()), out strBody);
            txtBody.Text = strBody;
            selectIndex = lstLogitem.SelectedIndex + (currentPage - 1) * PageCount;
        }

        private void btnExecute_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txtUrl.Text))
            {
                MessageBox.Show("Please enter Url!");
                txtUrl.Focus();
                return;
            }
            if (string.IsNullOrEmpty(txtHeader.Text))
            {
                MessageBox.Show("Please enter request header!");
                txtHeader.Focus();
                return;
            }
            if (string.IsNullOrEmpty(txtBody.Text))
            {
                MessageBox.Show("Please enter request body!");
                txtBody.Focus();
                return;
            }

            SendOnceRequest();
        }

        private void btnExecuteBatch_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txtUrl.Text))
            {
                MessageBox.Show("Please enter Url!");
                txtUrl.Focus();
                return;
            }

            btnTotal.Enabled = false;
            btn200.Enabled = false;
            btn400.Enabled = false;
            btn500.Enabled = false;
            btnNoads.Enabled = false;

            SendBatchRequest();
        }

        private void txtHeader_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Modifiers == Keys.Control && e.KeyCode == Keys.A)
            {
                ((TextBox)sender).SelectAll();
            }
        }

        private void txtBody_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Modifiers == Keys.Control && e.KeyCode == Keys.A)
            {
                ((TextBox)sender).SelectAll();
            }
        }

        private void LogParse_Load(object sender, EventArgs e)
        {
            asc.ControllInitializeSize(this);
        }

        private void LogParser_SizeChanged(object sender, EventArgs e)
        {
            asc.ControlAutoSize(this);
        }

        private void btnTotal_Click(object sender, EventArgs e)
        {
            if (responseList != null)
            {
                lstResposeResult.BeginUpdate();
                if (lstResposeResult.Items.Count > 0)
                {
                    lstResposeResult.Items.Clear();
                }
                foreach (IBdiHttpWebResponse response in responseList)
                {
                    ListViewItem Item = new ListViewItem();
                    Item.SubItems[0].Text = lstResposeResult.Items.Count.ToString();
                    Item.SubItems.Add(response.StatusCode);
                    Item.SubItems.Add(response.MachineName);
                    Item.SubItems.Add(response.RequestStreamLatency.ToString());
                    Item.SubItems.Add(response.ResponseSize.ToString());
                    Item.SubItems.Add(response.IsNoAds.ToString());
                    Item.SubItems.Add(response.LogRecordId.ToString());

                    lstResposeResult.Items.Add(Item);
                }
                lstResposeResult.EndUpdate();
            }
        }

        private void btn200_Click(object sender, EventArgs e)
        {
            if (responseList != null)
            {
                lstResposeResult.BeginUpdate();
                if (lstResposeResult.Items.Count > 0)
                {
                    lstResposeResult.Items.Clear();
                }
                foreach (IBdiHttpWebResponse response in responseList)
                {
                    if (response.StatusCode == "200")
                    {
                        ListViewItem Item = new ListViewItem();
                        Item.SubItems[0].Text = lstResposeResult.Items.Count.ToString();
                        Item.SubItems.Add(response.StatusCode);
                        Item.SubItems.Add(response.MachineName);
                        Item.SubItems.Add(response.RequestStreamLatency.ToString());
                        Item.SubItems.Add(response.ResponseSize.ToString());
                        Item.SubItems.Add(response.IsNoAds.ToString());
                        Item.SubItems.Add(response.LogRecordId.ToString());

                        lstResposeResult.Items.Add(Item);
                    }
                }
                lstResposeResult.EndUpdate();
            }
        }

        private void btn400_Click(object sender, EventArgs e)
        {
            if (responseList != null)
            {
                lstResposeResult.BeginUpdate();
                if (lstResposeResult.Items.Count > 0)
                {
                    lstResposeResult.Items.Clear();
                }
                foreach (IBdiHttpWebResponse response in responseList)
                {
                    if (response.StatusCode.StartsWith("4"))
                    {
                        ListViewItem Item = new ListViewItem();
                        Item.SubItems[0].Text = lstResposeResult.Items.Count.ToString();
                        Item.SubItems.Add(response.StatusCode);
                        Item.SubItems.Add(response.MachineName);
                        Item.SubItems.Add(response.RequestStreamLatency.ToString());
                        Item.SubItems.Add(response.IsNoAds.ToString());
                        Item.SubItems.Add(response.ResponseSize.ToString());
                        Item.SubItems.Add(response.LogRecordId.ToString());

                        lstResposeResult.Items.Add(Item);
                    }
                }
                lstResposeResult.EndUpdate();
            }
        }

        private void btn500_Click(object sender, EventArgs e)
        {
            if (responseList != null)
            {
                lstResposeResult.BeginUpdate();
                if (lstResposeResult.Items.Count > 0)
                {
                    lstResposeResult.Items.Clear();
                }
                foreach (IBdiHttpWebResponse response in responseList)
                {
                    if (response.StatusCode.StartsWith("5"))
                    {
                        ListViewItem Item = new ListViewItem();
                        Item.SubItems[0].Text = lstResposeResult.Items.Count.ToString();
                        Item.SubItems.Add(response.StatusCode);
                        Item.SubItems.Add(response.MachineName);
                        Item.SubItems.Add(response.RequestStreamLatency.ToString());
                        Item.SubItems.Add(response.ResponseSize.ToString());
                        Item.SubItems.Add(response.IsNoAds.ToString());
                        Item.SubItems.Add(response.LogRecordId.ToString());

                        lstResposeResult.Items.Add(Item);
                    }
                }
                lstResposeResult.EndUpdate();
            }
        }

        private void btnNoads_Click(object sender, EventArgs e)
        {
            if (responseList != null)
            {
                lstResposeResult.BeginUpdate();
                if (lstResposeResult.Items.Count > 0)
                {
                    lstResposeResult.Items.Clear();
                }
                foreach (IBdiHttpWebResponse response in responseList)
                {
                    if (response.IsNoAds)
                    {
                        ListViewItem Item = new ListViewItem();
                        Item.SubItems[0].Text = lstResposeResult.Items.Count.ToString();
                        Item.SubItems.Add(response.StatusCode);
                        Item.SubItems.Add(response.MachineName);
                        Item.SubItems.Add(response.RequestStreamLatency.ToString());
                        Item.SubItems.Add(response.ResponseSize.ToString());
                        Item.SubItems.Add(response.IsNoAds.ToString());
                        Item.SubItems.Add(response.LogRecordId.ToString());

                        lstResposeResult.Items.Add(Item);
                    }
                }
                lstResposeResult.EndUpdate();
            }
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            lstResposeResult.Items.Clear();
            txtTotal.Text = "0";
            txt200.Text = "0";
            txt400.Text = "0";
            txt500.Text = "0";
            txtNoads.Text = "0";
            if (responseList != null)
            {
                responseList = null;
            }
        }

        private void lstResposeResult_MouseClick(object sender, MouseEventArgs e)
        {
            int logRecordId = int.Parse(lstResposeResult.FocusedItem.SubItems[6].Text);

            string strHeader = BdiFileParser.GetRequestHeader(list[logRecordId].ToString());

            string[] headers = strHeader.Split('|');
            strHeader = string.Empty;
            foreach (string header in headers)
            {
                if (string.IsNullOrEmpty(header))
                {
                    continue;
                }
                if (!string.IsNullOrEmpty(strHeader))
                {
                    strHeader += Environment.NewLine;
                }
                int index = header.IndexOf("=");
                if (index > 0)
                {
                    if (header.Substring(0, index).ToUpper() == "X-FD-APPID")
                    {
                        strHeader += header.Substring(0, index) + ":" + "CDDD89A468E3781699EA1FA5D91447230DCD5E6A";
                    }
                    else
                    {
                        strHeader += header.Substring(0, index) + ":" + header.Substring(index + 1);
                    }
                }
            }

            txtHeader.Text = strHeader;

            string strBody;
            AdBaseRequestParser.GetBingRequestBody(BdiFileParser.GetRequestBody(list[logRecordId].ToString()), out strBody);
            txtBody.Text = strBody;
            selectIndex = logRecordId;
        }

        private void Initialize()
        {
            try
            {
                txtLogFile.Text = BdiFileParser.GetLogFileName();

                // Initialize Respose Result list
                lstResposeResult.GridLines = true;
                lstResposeResult.FullRowSelect = true;
                lstResposeResult.View = View.Details;
                lstResposeResult.Scrollable = true;
                lstResposeResult.MultiSelect = false;
                lstResposeResult.HeaderStyle = ColumnHeaderStyle.Clickable;

                lstResposeResult.Columns.Add("#", 50, HorizontalAlignment.Center);
                lstResposeResult.Columns.Add("HttpStatusCode", 90, HorizontalAlignment.Center);
                lstResposeResult.Columns.Add("Host", 120, HorizontalAlignment.Center);
                lstResposeResult.Columns.Add("ResponseLatency", 100, HorizontalAlignment.Center);
                lstResposeResult.Columns.Add("ResponseSize", 90, HorizontalAlignment.Center);
                lstResposeResult.Columns.Add("Noads", 50, HorizontalAlignment.Center);
                lstResposeResult.Columns.Add("LogRecordId", 75, HorizontalAlignment.Center);

                lstResposeResult.Visible = true;

                btnPrev.Enabled = false;
                btnNext.Enabled = false;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void SendOnceRequest()
        {
            try
            {
                string strUrl = txtUrl.Text.ToString().Trim();
                if (!strUrl.StartsWith("http://") && !strUrl.StartsWith("https://"))
                {
                    strUrl = "http://" + strUrl;
                }

                string requestBody = txtBody.Text.Trim();
                NameValueCollection requestHeader = GetRequestHeaders();
                string machineName = strUrl.Substring(strUrl.IndexOf("//") + 2, strUrl.Substring(strUrl.IndexOf("//") + 2).IndexOf("/"));

                IBdiRequeParameters requestParameter = new IBdiRequeParameters();
                requestParameter.RequestHeaders = requestHeader;
                requestParameter.RequestBody = requestBody;
                requestParameter.Url = strUrl;
                requestParameter.MachineName = machineName;
                Int64 logRecordId = selectIndex;
                using (IBdiHttpWebResponse bdiHttpWebResponse = BdiHttpWebRequest.CreatePostHttpResponse(requestParameter))
                {
                    bdiHttpWebResponse.LogRecordId = logRecordId;
                    bdiHttpWebResponse.MachineName = machineName;
                    this.Invoke(new UpdateResposeResultEventHandler(UpdateResposeResult), new object[] { bdiHttpWebResponse });
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void UpdateResposeResult(IBdiHttpWebResponse bdiResponse)
        {
            lock (lstResposeResult)
            {
                lstResposeResult.BeginUpdate();
                ListViewItem Item = new ListViewItem();
                Item.SubItems[0].Text = lstResposeResult.Items.Count.ToString();
                Item.SubItems.Add(bdiResponse.StatusCode);
                Item.SubItems.Add(bdiResponse.MachineName);
                Item.SubItems.Add(bdiResponse.RequestStreamLatency.ToString());
                Item.SubItems.Add(bdiResponse.ResponseSize.ToString());
                Item.SubItems.Add(bdiResponse.IsNoAds.ToString());
                Item.SubItems.Add(bdiResponse.LogRecordId.ToString());

                lstResposeResult.Items.Add(Item);
                lstResposeResult.EndUpdate();
                lstResposeResult.Items[lstResposeResult.Items.Count - 1].EnsureVisible();
            }
            if (bdiResponse.StatusCode == "200")
            {
                lock (txt200)
                {
                    txt200.Text = (Convert.ToInt32(txt200.Text) + 1).ToString();
                    txt200.Update();
                }
            }
            else if (bdiResponse.StatusCode.StartsWith("4"))
            {
                lock (txt400)
                {
                    txt400.Text = (Convert.ToInt32(txt400.Text) + 1).ToString();
                    txt400.Update();
                }
            }
            else if (bdiResponse.StatusCode.StartsWith("5"))
            {
                lock (txt500)
                {
                    txt500.Text = (Convert.ToInt32(txt500.Text) + 1).ToString();
                    txt500.Update();
                }
            }
            if (bdiResponse.IsNoAds)
            {
                lock (txtNoads)
                {
                    txtNoads.Text = (Convert.ToInt32(txtNoads.Text) + 1).ToString();
                    txtNoads.Update();
                }
            }
            lock (txtTotal)
            {
                txtTotal.Text = (Convert.ToInt32(txtTotal.Text) + 1).ToString();
                txtTotal.Update();
            }
            if (responseList == null)
            {
                responseList = new ArrayList();
            }
            responseList.Add(bdiResponse);
        }

        private void SendBatchRequest()
        {
            try
            {
                string strUrl = txtUrl.Text.ToString().Trim();
                if (!strUrl.StartsWith("http://") && !strUrl.StartsWith("https://"))
                {
                    strUrl = "http://" + strUrl;
                }
                int number = list.Count / (int)numCount.Value;
                int threadCount = (int)numCount.Value;
                int threadNumber = 0;
                for (int i = 0; i < threadCount; i++)
                {
                    int start = i;
                    Task t = new Task(() => SendBatchRequest(strUrl, start, threadCount));
                    t.Start();
                    t.ContinueWith(task =>
                    {
                        threadNumber++;
                        if (threadNumber == threadCount)
                        {
                            btnTotal.Enabled = true;
                            btn200.Enabled = true;
                            btn400.Enabled = true;
                            btn500.Enabled = true;
                            btnNoads.Enabled = true;
                        }
                    });
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void SendBatchRequest(string strUrl, int index, int number)
        {
            string machineName = strUrl.Substring(strUrl.IndexOf("//") + 2, strUrl.Substring(strUrl.IndexOf("//") + 2).IndexOf("/"));
            string strBody;

            for (int i = index; i < list.Count; )
            {
                string str = list[i].ToString();
                IBdiRequeParameters requestParameter = new IBdiRequeParameters();
                requestParameter.RequestHeaders = GetRequestHeaders(BdiFileParser.GetRequestHeader(str));
                AdBaseRequestParser.GetBingRequestBody(BdiFileParser.GetRequestBody(str), out strBody);
                requestParameter.RequestBody = strBody;
                requestParameter.Url = strUrl;
                requestParameter.MachineName = machineName;

                using (IBdiHttpWebResponse bdiHttpWebResponse = BdiHttpWebRequest.CreatePostHttpResponse(requestParameter))
                {
                    bdiHttpWebResponse.MachineName = machineName;
                    bdiHttpWebResponse.LogRecordId = i;
                    this.Invoke(new UpdateResposeResultEventHandler(UpdateResposeResult), new object[] { bdiHttpWebResponse });
                }
                i = i + number;
            }
        }

        private NameValueCollection GetRequestHeaders()
        {
            NameValueCollection requestHeaders = new NameValueCollection();

            string[] headers = txtHeader.Text.Split(Environment.NewLine.ToCharArray());
            foreach (string header in headers)
            {
                if (string.IsNullOrEmpty(header))
                {
                    continue;
                }
                int index = header.IndexOf(":");
                if (index > 0)
                {
                    if (header.Substring(0, index).ToUpper() == "X-FD-APPID")
                    {
                        requestHeaders.Add(header.Substring(0, index), "CDDD89A468E3781699EA1FA5D91447230DCD5E6A");
                    }
                    else
                    {
                        requestHeaders.Add(header.Substring(0, index), header.Substring(index + 1));
                    }
                }
            }
            return requestHeaders;
        }

        private NameValueCollection GetRequestHeaders(string strHeader)
        {
            NameValueCollection requestHeaders = new NameValueCollection();
            string[] headers = strHeader.Split('|');
            foreach (string header in headers)
            {
                if (string.IsNullOrEmpty(header))
                {
                    continue;
                }
                int index = header.IndexOf("=");
                if (index > 0)
                {
                    if (header.Substring(0, index).ToUpper() == "X-FD-APPID")
                    {
                        requestHeaders.Add(header.Substring(0, index), "CDDD89A468E3781699EA1FA5D91447230DCD5E6A");
                    }
                    else
                    {
                        requestHeaders.Add(header.Substring(0, index), header.Substring(index + 1));
                    }
                }
            }
            return requestHeaders;
        }
    }
}
